package me.hetong.wecom;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 企业微信群机器人消息
 *
 * @author hetong
 */
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class TtGroupRobot {

    private static String sysInfo;
    private Map<String, String[]> urlMap = new HashMap<>();// 不同环境的机器人配置 dev,test,pro
    private String userIdFlag = "userId";// 用户ID标记,比如来自哪个用户的操作（只从header中获取）

    static {

        String osName = System.getProperty("os.name"); // 获取操作系统名称
        String userName = System.getProperty("user.name"); // 获取当前登录用户名

        sysInfo = StrUtil.format("{}/{}", osName, userName);
        StaticLog.info("操作系统/用户名：" + sysInfo);
    }

    public static TtGroupRobot create() {
        return new TtGroupRobot();
    }

    /**
     * 初始化机器人链接
     *
     * @param env
     * @param urlArr
     */
    public void initUrl(String env, String[] urlArr) {
        this.getUrlMap().put(env, urlArr);
    }

    /**
     * 新增机器人链接
     *
     * @param env
     * @param urlArr
     */
    public void addUrl(String env, String[] urlArr) {
        String[] oldUrlArr = this.getUrlMap().get(env);
        String[] newUrlArr = ArrayUtil.addAll(oldUrlArr, urlArr);
        this.getUrlMap().put(env, newUrlArr);
    }

    /**
     * 发送普通文本类型消息
     *
     * @param env  当前环境变量
     * @param text
     */
    public void sendTextType(String env, String text) {
        sendTextType(new Message(env), text);
    }

    /**
     * 发送普通文本类型消息
     *
     * @param message
     * @param text
     */
    public void sendTextType(Message message, String text) {

        try {

            StaticLog.info("机器人-发送消息:{}", text);

            /**
             * {
             *     "msgtype": "text",
             *     "text": {
             *         "content": "广州今日天气:29度，大部分多云，降雨概率:60%",
             * 		"mentioned_list":["wangqing","@all"],
             * 		"mentioned_mobile_list":["13800001111","@all"]
             *     }
             * }
             */

            JSONObject textJson = new JSONObject();
            textJson.put("content", text);
            if (ArrayUtil.isNotEmpty(message.getAtArray())) {
                textJson.put("mentioned_mobile_list", message.getAtArray());
            }

            JSONObject msgJson = new JSONObject();
            msgJson.put("msgtype", "text");
            msgJson.put("text", textJson);

            String jsonString = JSONUtil.toJsonStr(msgJson);

            HttpUtil.post(RandomUtil.randomEle(urlMap.get(message.getEnv())), jsonString);
        } catch (Exception e) {
            StaticLog.error("机器人-发送普通文本消息异常:{}", e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 发送普通文本类型消息
     *
     * @param message
     */
    public void sendTextType(Message message) {

        try {
            StringBuilder sb = new StringBuilder();

            if (StrUtil.isNotBlank(message.getTitle())) {
                sb.append("标题：").append(message.getTitle()).append("\n");
            }

            sb.append("运行环境：").append(message.getEnv()).append("\n");
            sb.append(sysInfo).append(" 线程：").append(Thread.currentThread().getName()).append("\n");

            if (message.getPoint() != null) {
                Signature signature = message.getPoint().getSignature();
                String declaringTypeName = signature.getDeclaringTypeName();// 包名类名
                String name = signature.getName();// 方法名
                sb.append("执行方法：").append(declaringTypeName).append(".").append(name).append("\n");
            }

            if (message.getRequestAttributes() != null) {

                HttpServletRequest req = ((ServletRequestAttributes) message.getRequestAttributes()).getRequest();

                sb.append("接口：").append(req.getMethod()).append(" ").append(req.getRequestURI()).append("\n");

                String userId = req.getHeader(userIdFlag);
                if (StrUtil.isNotBlank(userId)) {
                    sb.append("操作用户：").append(userId).append("\n");
                }

                String queryString = req.getQueryString();
                if (StrUtil.isNotBlank(queryString)) {
                    sb.append("查询参数：").append(queryString).append("\n");
                }

                try {
                    BufferedReader reader = req.getReader();
                    if (reader != null) {
                        String body = reader.lines().collect(Collectors.joining());
                        if (StrUtil.isNotBlank(body)) {
                            sb.append("请求体参数：").append(body).append("\n");
                        }
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }

            if (message.getInterval() > 0) {
                sb.append("执行时间：").append(message.getInterval()).append(" 毫秒\n");
            }

            sb.append("消息ID：").append(IdUtil.simpleUUID()).append("\n");

            Exception e = message.getE();
            if (e != null) {
                try {
                    String jsonStr = JSONUtil.toJsonStr(e);
                    sb.append("异常摘要：").append(jsonStr).append("\n");
                } catch (Exception ex) {
                    sb.append("异常摘要：").append(e.getMessage()).append("\n");
                }
                e.printStackTrace();
            }

            Throwable t = message.getT();
            if (t != null) {
                try {
                    String jsonStr = JSONUtil.toJsonStr(t);
                    sb.append("错误摘要：").append(jsonStr).append("\n");
                } catch (Exception ex) {
                    sb.append("错误摘要：").append(t.getMessage()).append("\n");
                }
                t.printStackTrace();
            }

            String s = StrUtil.removeSuffix(sb.toString(), "\n");
            sendTextType(message, s);

        } catch (Exception ex) {
            sendTextType(message.getEnv(), "机器人-发送消息时异常" + ex.getMessage());
            ex.printStackTrace();
        }

    }

    /**
     * 消息体
     */
    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Message {

        private String env;
        private JoinPoint point;
        private long interval;
        private Exception e;
        private Throwable t;
        private String title;
        private String[] atArray;

        /**
         * 在多线程场景下，子显示可能无法获取到主显示的requestAttributes，需要显示传递
         */
        private RequestAttributes requestAttributes;

        public Message(String env) {
            this.env = env;
        }

    }

    public static void main(String[] args) {
        TtGroupRobot ttGroupRobot = new TtGroupRobot();
        ttGroupRobot.setUserIdFlag("userId");
        ttGroupRobot.initUrl("dev", new String[]{"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0e0df479-c386-4454-902d-6282433d4d28"});
        Message message = new Message();
        message.setEnv("dev");
        message.setE(new Exception("这是异常测试"));
        message.setAtArray(new String[]{"18701267228"});
        message.setTitle("你好");
        ttGroupRobot.sendTextType(message);
    }

}
